package com.example.gateway.filter;

import com.alibaba.fastjson.JSONObject;
import com.example.gateway.entity.SysUser;
import com.example.gateway.service.PermissionService;
import com.example.gateway.util.TokenCheckUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: TODO
 * @author: 周天翼
 * @date: 2020年07月30日 23:09
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private TokenCheckUtils tokenCheckUtils;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("-------------开始调用0号过滤器--------------");
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String url= request.getURI().getPath();
        Pattern p = Pattern.compile("^/[a-zA-Z0-9]+/admin(/[a-zA-Z0-9_]*)*$");
        Pattern p1 = Pattern.compile("^/[a-zA-Z0-9]+/user(/[a-zA-Z0-9_]*)*$");
        boolean m = p.matcher(url).find();
        boolean m1 = p1.matcher(url).find();
        log.info("当前请求访问接口:"+url);
        //访问用户体系的请求
        if(StringUtils.startsWith(url,"/usersystem/")||StringUtils.startsWith(url,"/usersystemws/")){
            log.info("访问"+url+"的请求，由用户体系自行校验权限，放行");
            return chain.filter(exchange);
        }
        //访问有/admin/标注的请求 进行权限校验
        else if( m || m1 ){
            //从请求头部获取token
            String token = request.getHeaders().getFirst("X-Access-Token");
             //不包含token，拒绝请求
            if(StringUtils.isEmpty(token)){
                log.info("请求不包含token，拒绝访问");
                return failResponse(response,"Empty Token");
            }
            //校验token有效性,获取用户信息,通过用户名获取用户对应的角色,查看角色拥有的权限是否包含用户访问的路径
            else{
                try {
                    SysUser user = tokenCheckUtils.checkUserTokenIsEffect(token);
                    int flag = 0;
                    StringBuilder URI = new StringBuilder();
                    for(int i=0;i<url.length();i++){
                        char c = url.charAt(i);
                        if(c =='/'){
                            if(flag++ == 2) break;
                        }
                        URI.append(c);
                    }
                    log.info("用户当前访问接口为:"+url);
                    log.info("剪切处理后的接口为:"+URI);
                    Map<String,Object> map = new HashMap<>();
                    map.put("username",user.getUsername());
                    map.put("url",URI.toString());
                    List<Map<String, Object>> list = permissionService.queryByUser(map);
                    if(list==null||list.size()==0){
                        log.info("当前用户不具备访问该接口权限:"+list);
                        throw new Exception("Access Deny");
                    }else{
                        log.info("当前用户拥有权限："+list);
                        Consumer<HttpHeaders> httpHeaders = httpHeader -> {
                            httpHeader.set("userId", user.getId());
                        };
                        request.mutate().headers(httpHeaders).build();
                        exchange.mutate().request(request).build();
                        return chain.filter(exchange);
                    }
                } catch (Exception e) {
                    log.info("访问异常:{}",e.getMessage());
                    return failResponse(response,e.getMessage());
                }
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private Mono<Void> failResponse(ServerHttpResponse response,String message){
        JSONObject object = new JSONObject();
        object.put("success","false");
        object.put("message",message);
        object.put("timstamp",System.currentTimeMillis());
        byte[] bits = object.toJSONString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }

}
